﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace rehot.core
{
    using SanlieHash;

    public class HotEvents
    {
        internal HotType _hottype { get; set; }
        internal Dictionary<string, EventInfo> _events { get; set; }
        internal void Lose()
        {
            _hottype = null;
            if (_events != null)
            {
                _events.Clear();
                _events = null;
            }
        }
        public HotEvents(HotType hotType)
        {
            this._hottype = hotType;
            var runtime_events = this._hottype._type.GetEvents();
            this._events = new Dictionary<string, EventInfo>(runtime_events.Length);
            string id;
            foreach (var _event in runtime_events)
            {
                id = FastHash.GetSM3(_event.Name);
                if (!this._events.ContainsKey(id)) this._events.Add(FastHash.GetSM3(_event.Name), _event);
                else this._events[id] = _event;
            }
        }
        public IEnumerable<string> AllEventId()
        {
            foreach (var key in _events.Keys) yield return key;
        }
        public bool Exist(string name)
        {
            return !string.IsNullOrEmpty(FindEventId(name));
        }
        public string FindEventId(string name)
        {
            var id = FastHash.GetSM3(name);
            if (_events.ContainsKey(id)) return id;
            return string.Empty;
        }
        public string ReadNameById(string id)
        {
            if (_events.ContainsKey(id)) return _events[id].Name;
            return string.Empty;
        }
        public object AddByEventId(object obj, string id, params IHotEvent[] events)
        {
            if (!_events.ContainsKey(id)) throw new EntryPointNotFoundException(id);
            var method = _events[id].GetAddMethod();
            if (obj == null && !method.IsStatic) throw new ArgumentNullException(id); //非静态需要传入实例

            return method.Invoke(obj, HotEvent.Read(events));
        }
        public object RemoveByEventId(object obj, string id, params IHotEvent[] events)
        {
            if (!_events.ContainsKey(id)) throw new EntryPointNotFoundException(id);
            var method = _events[id].GetRemoveMethod();
            if (obj == null && !method.IsStatic) throw new ArgumentNullException(id); //非静态需要传入实例

            return method.Invoke(obj, HotEvent.Read(events));
        }
        public object RasieByEventId(object obj, string id, params IHotParam[] _params)
        {
            if (!_events.ContainsKey(id)) throw new EntryPointNotFoundException(id);
            var method = _events[id].GetRaiseMethod();
            if (obj == null && !method.IsStatic) throw new ArgumentNullException(id); //非静态需要传入实例
            return method.Invoke(obj, HotParam.Read(_params));
        }
        public Tout RasieByEventId<Tout>(object obj, string id, params IHotParam[] _params)
        {
            var rlt = RasieByEventId(obj, id, _params);
            if (rlt is Tout rlt1) return rlt1;
            return default;
        }
        public HotObject RasieUnknownByEventId(object obj, string id, params IHotParam[] _params)
        {
            if (!string.IsNullOrEmpty(id))
            {
                var rlt = RasieByEventId(obj, id, _params);
                if (rlt != null) return new HotObject(rlt);
            }
            return HotObject.Null;
        }
        public object Add(object obj, string name, params IHotEvent[] events)
        {
            var id = FastHash.GetSM3(name);
            return AddByEventId(obj, id, events);
        }
        public object Remove(object obj, string name, params IHotEvent[] events)
        {
            var id = FastHash.GetSM3(name);
            return RemoveByEventId(obj, id, events);
        }
        public object Rasie(object obj, string name, params IHotParam[] _params)
        {
            var id = FastHash.GetSM3(name);
            return RasieByEventId(obj, id, _params);
        }
        public Tout Rasie<Tout>(object obj, string name, params IHotParam[] _params)
        {
            var id = FastHash.GetSM3(name);
            return RasieByEventId<Tout>(obj, id, _params);
        }
        public HotObject RasieUnknown(object obj, string name, params IHotParam[] _params)
        {
            var id = FastHash.GetSM3(name);
            return RasieUnknownByEventId(obj, id, _params);
        }
    }
}
